/*    Copyright 2010 Tobias Marschall
 *
 *    This file is part of MoSDi.
 *
 *    MoSDi is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    MoSDi is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with MoSDi.  If not, see <http://www.gnu.org/licenses/>.
 */

package mosdi.util;

import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.NoSuchElementException;

public class SingletonList<T> implements List<T> {
	private T entry;
	
	public SingletonList(T entry) {
		this.entry = entry;
	}
	
	@Override
	public void add(int index, T element) { throw new UnsupportedOperationException(); }
	@Override
	public boolean add(T e) { throw new UnsupportedOperationException(); }
	@Override
	public boolean addAll(Collection<? extends T> c) { throw new UnsupportedOperationException(); }
	@Override
	public boolean addAll(int index, Collection<? extends T> c) { throw new UnsupportedOperationException(); }
	@Override
	public void clear() { throw new UnsupportedOperationException(); }
	@Override
	public boolean contains(Object o) { return entry.equals(o); }
	@Override
	public boolean containsAll(Collection<?> c) {
		for (Object o : c) {
			if (!entry.equals(o)) return false;
		}
		return true;
	}

	@Override
	public T get(int index) {
		if (index!=0) throw new IndexOutOfBoundsException(Integer.toString(index));
		return entry;
	}

	@Override
	public int indexOf(Object o) {
		if (o==null) return entry==null?0:-1;
		if (entry==null) return -1;
		return entry.equals(o)?0:-1;
	}

	@Override
	public boolean isEmpty() {
		return false;
	}

	private class SingletonListIterator implements ListIterator<T> {
		// only two positions are possible: 0 (before only element) and 1 (after only element)
		private int pos;
		private SingletonListIterator() { 
			pos = 0;
		}
		private SingletonListIterator(int pos) {
			this.pos = pos;
		}
		@Override
		public void add(T e) { throw new UnsupportedOperationException(); }
		@Override
		public boolean hasNext() {
			return pos == 0;
		}
		@Override
		public boolean hasPrevious() {
			return pos == 1;
		}  
		@Override
		public T next() {
			if (pos!=0) throw new NoSuchElementException();
			pos += 1;
			return entry;
		}
		@Override
		public int nextIndex() {
			return pos;
		}
		@Override
		public T previous() {
			if (pos!=1) throw new NoSuchElementException();
			pos -= 1;
			return entry;
		}
		@Override
		public int previousIndex() {
			return pos-1;
		}
		@Override
		public void remove() { throw new UnsupportedOperationException(); }
		@Override
		public void set(T e) { throw new UnsupportedOperationException(); }
	}
	
	@Override
	public Iterator<T> iterator() { return new SingletonListIterator(); }
	@Override
	public int lastIndexOf(Object o) { return indexOf(o); }
	@Override
	public ListIterator<T> listIterator() { return new SingletonListIterator(); }
	@Override
	public ListIterator<T> listIterator(int index) {
		if ((index<0) || (index>1)) throw new IndexOutOfBoundsException();
		return new SingletonListIterator(index);
	}

	@Override
	public T remove(int index) { throw new UnsupportedOperationException(); }
	@Override
	public boolean remove(Object o) { throw new UnsupportedOperationException(); }
	@Override
	public boolean removeAll(Collection<?> c) { throw new UnsupportedOperationException(); }
	@Override
	public boolean retainAll(Collection<?> c) { throw new UnsupportedOperationException(); }
	@Override
	public T set(int index, T element) {
		if (index!=0) throw new IndexOutOfBoundsException(Integer.toString(index));
		T former = entry;
		entry = element;
		return former;
	}

	@Override
	public int size() {	return 1; }

	@Override
	public List<T> subList(int fromIndex, int toIndex) { throw new UnsupportedOperationException(); }

	@Override
	public Object[] toArray() {
		Object[] array = {entry};
		return array;
	}

	@SuppressWarnings("hiding")
	@Override
	public <T> T[] toArray(T[] a) { throw new UnsupportedOperationException(); }

}
